import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.Set;

public class IOWorker implements Runnable {
    @Override
    public void run() {
        try {
            Selector selector = Selector.open();
            ServerSocketChannel channel = ServerSocketChannel.open();
            channel.configureBlocking(false);
            ServerSocket socket = channel.socket();

            socket.bind(new InetSocketAddress("localhost", 10800));

            channel.register(selector, channel.validOps());
            while (true) {
                selector.select();
                Iterator iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = (SelectionKey)iterator.next();
                    iterator.remove();
                    if (!key.isValid()) {
                        continue;
                    }
                    if (key.isAcceptable()) {
                        ServerSocketChannel ssc = (ServerSocketChannel)
                                key.channel();
                        SocketChannel sc = ssc.accept();
                        sc.configureBlocking(false);
                        sc.register(selector, sc.validOps());
                    }



                    if(key.isReadable()){
                        SocketChannel client = (SocketChannel)
                                key.channel();
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 3);
                        // 7.5.2 将缓冲区清空以备下次读取
                        byteBuffer.clear();
                        int readCount = -1;
                        readCount = client.read(byteBuffer);
                        // 有数据 则打印输出
                        String receiveText = new String( byteBuffer.array(),0,readCount);
                        System.out.println("服务器端接受客户端数据--:"+receiveText);
                        if (readCount == -1) {
                            Socket socket2 = client.socket();
                            SocketAddress remoteAddr = socket2.getRemoteSocketAddress();
                            System.out.println(remoteAddr);
                            client.register(selector, SelectionKey.OP_WRITE);
                        }


                    }else if(key.isWritable()){
                            SocketChannel client = (SocketChannel)
                                    key.channel();
                        Charset charset = Charset.forName("UTF-8");
                        CharsetEncoder encoder = charset.newEncoder();
                        CharBuffer charBuffer = CharBuffer.allocate(32);
                        charBuffer.put("Hello World");
                        charBuffer.flip();
                        ByteBuffer content = encoder.encode(charBuffer);
                        client.write(content);
                        client.close();
                        key.cancel();
                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 基本的NIO模式
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
//        NIO();
//        slice();

        IOWorker ioWorker = new IOWorker();
        new Thread(ioWorker).start();
    }

    /**
     * 分片区
     * @throws Exception
     */
    private static void slice() throws Exception{

        //创建一个容量为10的字节缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(10);

        //设置缓冲区中的数据
        for (int i=0; i<buffer.capacity(); ++i) {
            buffer.put(i, (byte) i);
        }
        //手动设置状态变量，创建一个包含原缓冲区index3-6的子缓冲区（分片）
        buffer.position(0);
        buffer.limit(7);
        ByteBuffer slice = buffer.slice();
        //对新创建的子缓冲区中每个数据乘10操作
        for (int i=0; i<slice.capacity(); ++i) {
            byte b = slice.get(i);
            b*=10;
            slice.put(i, b);
        }
        //重设状态变量
        buffer.position(0);
        buffer.limit(buffer.capacity());
        while (buffer.hasRemaining()) {
            System.out.println(buffer.get());
        }
    }

    /**
     * 普通的IO读写
     * @throws Exception
     */
    private static void NIO() throws Exception{
        RandomAccessFile formFile = new RandomAccessFile("src\\a.txt", "rw");
        RandomAccessFile toFile = new RandomAccessFile("src\\b.txt", "rw");

        //获取channel
        FileChannel fromChannel = formFile.getChannel();
        FileChannel toChannel = toFile.getChannel();

        // 定义缓冲大小
        int bufSize = 1024*4;

        // 定义缓冲
        ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize);

        int len = 0;

        // 将数据从源channel写入到缓冲区
        while((len=fromChannel.read(byteBuffer)) !=-1 ){

            //切换到读模式
            byteBuffer.flip();

            //读取缓冲区数据写到目标channel
            toChannel.write(byteBuffer);

            // 清空缓冲
            byteBuffer.clear();
        }

        // 释放资源
        toChannel.close();
        fromChannel.close();
    }

    }


